#include <limits>

template<typename T>
class myvector
{
public:
    myvector():m_size(0),m_capacity(0),m_data(nullptr)
    {}

    explicit myvector(size_t n):m_size(n),m_capacity(n),m_data(nullptr)
    {
        if(m_capacity > 0)
        {
            m_data = malloc(m_capacity * sizeof(T));
        }
        for(int i = 0; i < m_size; i++)
        {
            construct(&m_data[i]);
        }
    }

    explicit myvector(size_t n, const T& val):m_size(n),m_capacity(n),m_data(nullptr)
    {
        if(m_capacity > 0)
        {
            m_data = malloc(m_capacity * sizeof(T));
        }
        for(int i = 0; i < m_size; i++)
        {
            construct(&m_data[i],val);
        }
    }

    ~myvector()
    {
        for(int i = 0; i < m_size; i++)
        {
            destroy(&m_data[i]);
        }
        if(m_data)
        {
            free(m_data);
            m_data = nullptr;
        }
    }

    myvector(const myvector& other):m_size(other.m_size),m_capacity(other.m_size)
    {
        if(m_capacity > 0)
        {
            m_data = reinterpret_cast<T*>(malloc(m_capacity * sizeof(T)));
        }
        for(int i = 0; i < m_size; i++)
        {
            construct(&m_data[i],other.m_data[i]);
        }
    }

    myvector(myvector&& other):m_size(other.m_size),m_capacity(other.m_capacity),m_data(other.m_data)
    {
        //移动构造函数，直接将other的资源转移过来
        other.m_data = nullptr;
        other.m_size = other.m_capacity = 0;
    }
    
    myvector& operator=(const myvector& other)
    {
        if(this == &other)
        {
            return *this;
        }

        for(int i = 0; i < m_size; i++)
        {
            destroy(&m_data[i]);
        }
        if(m_data)
        {
            free(m_data);
        }

        m_size = other.m_size;
        m_capacity = other.m_capacity;
        if(m_capacity > 0)
        {
            m_data = reinterpret_cast<T*>(malloc(m_capacity * sizeof(T)));
        }
        for(int i = 0; i < m_size; i++)
        {
            construct(&m_data[i],other.m_data[i]);
        }
        
        return *this;
    }

    myvector& operator=(myvector&& other)
    {
        if(this == &other)
        {
            return *this;
        }
        
        for(int i = 0; i < m_size; i++)
        {
            destroy(&m_data[i]);
        }
        if(m_data)
        {
            free(m_data);
        }

        //移动完资源后，将other的资源置空
        m_size = other.m_size;
        m_capacity = other.m_capacity;
        m_data = other.m_data;
        other.m_size = 0;
        other.m_capacity = 0;
        other.m_data = nullptr;
        return *this;
    }

    void reserve(size_t n)
    {
        if(n > m_capacity)
        {
            m_capacity = n;
            
            //申请新内存，复制（移动）所有元素
            T* tmp = reinterpret_cast<T*>(malloc(m_capacity * sizeof(T)));
            for(int i = 0; i < m_size; i++)
            {
                construct(&tmp[i], std::move(m_data[i]));
            }

            //清理旧vector
            for(int i  = 0; i < m_size; i++)
            {
                destroy(&m_data[i]);
            }
            if(m_data)
            {
                free(m_data);
            }
            m_data = tmp;
        }
    }

    void push_back(const T& val)
    {
        //std::cout << "push_back(const T& val)" << std::endl;
        if(m_size == m_capacity)
        {
            //预防size_t类型溢出
            if (m_capacity > (std::numeric_limits<size_t>::max() / 2)) 
            {
                throw std::length_error("vector capacity exceeds maximum limit");
            }

            size_t newcapacity = m_capacity == 0 ? 1 : (m_capacity * 2);
            reserve(newcapacity);
        }
        construct(&m_data[m_size++], val);
    }

    void push_back(T&& val)
    {
        //std::cout << "push_back(T&& val)" << std::endl;
        emplace_back(std::move(val)); //添加右值时直接调用emplace_back，std::move用来维持右值属性
    }

    template<typename... Args>
    void emplace_back(Args&&... args)
    {
        //std::cout << "emplace_back(Args&&... args)" << std::endl;
        if(m_size == m_capacity)
        {
            //预防size_t类型溢出
            if (m_capacity > (std::numeric_limits<size_t>::max() / 2)) 
            {
                throw std::length_error("vector capacity exceeds maximum limit");
            }

            size_t newcapacity = m_capacity == 0 ? 1 : (m_capacity * 2); //容量为0时，新容量为1，否则2倍扩容
            reserve(newcapacity);
        }
        construct(&m_data[m_size++], std::forward<Args>(args)...); //完美转发
    }

    void pop_back()
    {
        if(m_size == 0)
        {
            return;
        }
        destroy(&m_data[m_size--]);
    }

    void swap(myvector& other)
    {
        std::swap(m_size, other.m_size);
        std::swap(m_capacity, other.m_capacity);
        std::swap(m_data, other.m_data);
    }

    void clear()
    {
        for(int i = 0; i < m_size; i++)
        {
            destroy(&m_data[i]);
        }
        m_size = 0;
    }

    T& operator[](size_t index)
    {
        if(index + 1 > m_size)
        {
            throw std::out_of_range("unreachable place of vector!");
        }
        return m_data[index];
    }

    //重载const版本，考虑到const myvector对象不能直接返回元素的引用
    const T& operator[](size_t index) const
    {
        if(index + 1 > m_size)
        {
            throw std::out_of_range("unreachable place of vector!");
        }
        return m_data[index];
    }

    size_t size() const
    {
        return m_size;
    }

    size_t capacity() const
    {
        return m_capacity;
    }

    bool empty() const
    {
        return m_size == 0;
    }

private:
    //构造单个元素
    template<typename... Args>
    void construct(void* addr, Args&&... args)
    {
        new(addr) T(std::forward<Args>(args)...); //完美转发，使用placement_new构造对象
    }

    //销毁单个元素
    void destroy(void* addr)
    {
        reinterpret_cast<T*>(addr)->~T(); //显式调用析构函数销毁对象
    }

private:
    size_t m_size;
    size_t m_capacity;
    T *m_data;
};